home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-10 / zk203.zip / ZPROG.DOC < prev   
Text File  |  1990-10-15  |  32KB  |  791 lines

  1. PROGRAMMATIC INTERFACE DOCUMENT
  2.  
  3.  
  4. This file is intended for computer programmers who wish to access
  5. ZIPKEY directly from within their programs.  If you are not a
  6. computer programmer, you may ignore this file.
  7.  
  8.  
  9. The ZIPKEY Interrupt
  10.  
  11. When ZIPKEY is installed as a memory-resident program (using the
  12. ZIPKEY 4 command), it takes over one of the 8086's interrupts,
  13. INT 179 (decimal; it's B3 in hexadecimal).  This interrupt serves
  14. two functions: first, it is the method by which ZIPKEY detects if
  15. it has already been installed.  Second, it provides the interface
  16. by which computer programs can call ZIPKEY directly, to obtain
  17. zipcode-related services.
  18.  
  19. I conducted a survey of numerous computers before selecting INT
  20. 179 to be used by ZIPKEY.  I found no computers or peripherals
  21. that use this interrupt, and I am hopeful that there are none.
  22. If your computer does use INT 179, then ZIPKEY and the device or
  23. program using INT 179 will interfere with each other.  You can
  24. change the interrupt number ZIPKEY uses by modifying the ZIPKEY
  25. program itself: the number 179 is stored in the fourth byte of
  26. the ZIPKEY program code, immediately beyond the three-byte JMP
  27. instruction that begins the program.  This JMP occurs at the very
  28. start of the ZIPKEY.COM file, or immediately beyond the 512-byte
  29. header of the ZIPKEY.EXE file.  You can use a debugger or a hex
  30. editor to modify the byte to an unused interrupt number.
  31.  
  32.  
  33. Testing for ZIPKEY's Presence
  34.  
  35. Before you program attempts to call ZIPKEY, it may wish to verify
  36. that ZIPKEY has been installed, and report an error if it isn't.
  37. Otherwise, you program may crash when it tries to call code that
  38. isn't there.
  39.  
  40. You can test for ZIPKEY's presence by examining the INT 179
  41. handler, whose doubleword pointer is stored at offset 179*4 (=716
  42. =02CCH) within segment 0 of the 8086 memory space.  If ZIPKEY is
  43. installed, the doubleword points to its code segment.  Location
  44. 075H within that code segment contains the signature string
  45. ZIPKEY.  Thus, the following code sequence will check for
  46. ZIPKEY's presence:
  47.                                                               P-2
  48.  
  49. OUR_ZIPKEY:                ; our copy of the template
  50.   DB 'ZIPKEY'
  51.  
  52. CHECK_FOR_ZIPKEY:
  53.   PUSH DS                  ; save register value
  54.   SUB AX,AX                ; load zero
  55.   MOV DS,AX                ; point DS to 0 -- 8086 interrupts
  56.   MOV DS,WORD PTR 02CEH    ; fetch the segment part of INT 179
  57.   MOV SI,075H              ; point to signature in segment
  58.   PUSH CS                  ; push our code segment
  59.   POP ES                   ; set ES to our code segment
  60.   MOV DI,OFFSET OUR_ZIPKEY ; now ES:DI points to 'ZIPKEY'
  61.   MOV CX,3                 ; there are 3 words in 'ZIPKEY'
  62.   REPE CMPSW               ; does DS:75H point to 'ZIPKEY'?
  63.   POP DS                   ; restore register before jumping
  64.   JZ ZIPKEY_INSTALLED      ; jump if it does match
  65. ZIPKEY_NOT_INSTALLED:      ; it does not match
  66.  
  67. Following the ZIPKEY signature, at offset 07BH within the ZIPKEY
  68. code segment, is a single byte that is zero in the initial
  69. version of ZIPKEY, but will increment each time I release a
  70. ZIPKEY with new features or any other changes to the programmatic
  71. interface.  That way, if you program needs ZIPKEY to be of a
  72. sufficiently recent version, it can ensure that it is.  (You can
  73. also use the version number returned by the ZK_VERSION function
  74. described shortly.)
  75.  
  76.  
  77. ZIPKEY Calling Conventions
  78.  
  79. ZIPKEY's interface works similarly to that of the MS-DOS
  80. operating system, or the LIM-EMS specification.  The interface is
  81. specified in 8086 assembly language.  You load a function number
  82. into the AH register, and possibly other input parameters into
  83. other registers, then you execute an INT instruction with an
  84. appropriate interrupt number -- in ZIPKEY's case, the INT 179
  85. instruction.
  86.  
  87. When ZIPKEY has completed the function, it returns control to
  88. your program at the instruction following the INT 179.  The
  89. success of the call is indicated by the Carry flag: NoCarry (flag
  90. = 0) indicates success; Carry (flag = 1) indicates failure.  If
  91. the Carry flag is set, AL is usually set to an error code (the
  92. exceptions are those functions which, as mentioned in their
  93. following descriptions, return the state code for a suggested
  94. city).  Here are the possible error codes:
  95.  
  96. 0FDH is returned if ZIPKEY is busy. You will get this error only
  97.      if the program calling ZIPKEY had interrupted another
  98.      program which also happened to be in the middle of a ZIPKEY
  99.      call.  ZIPKEY is not reentrant, so it must refuse calls in
  100.      this situation.  If you think this interrupted-programming
  101.      scenario is possible, you should check for this possibility.
  102.      If ZIPKEY is busy, you should give the interrupted code a
  103.      chance to complete the ZIPKEY call, and try your call again
  104.      later.
  105.                                                               P-3
  106.  
  107. 0FEH is returned if you provided an illegal function number in
  108.      the AH register.
  109.  
  110. 0FFH is returned if the searching function requested failed to
  111.      find a valid entry, or even a suggested value.
  112.  
  113. Here are ZIPKEY's register-preserving conventions:  The AX
  114. register is clobbered by an INT 179 call; but all other 8086
  115. machine registers are preserved unless they are specifically
  116. named as having return values.  If a function returns an error,
  117. such return registers may be clobbered even if they contain no
  118. values in the return case.  For example, the ZK_STCITY_ZIP
  119. function returns values in BH, CX, and DX.  Except for AX, all
  120. other registers not mentioned are preserved (SI,DI,BP,DS,ES).
  121. The BH, CX, and DX registers may be clobbered even if the search
  122. fails (and Carry is returned).
  123.  
  124.  
  125. The ZIPKEY Functions
  126.  
  127. Following are the functions available to you when ZIPKEY is
  128. installed. For each function, you load the input registers with
  129. the values indicated, then invoke INT 179.
  130.  
  131. The names of the functions (ZK_VERSION, ZK_ABBR_ST, etc.) have no
  132. significance to ZIPKEY-- I present them merely as suggested names
  133. if you wish to implement a library of calls; and also so that I
  134. can refer to the functions by name.
  135.  
  136. ZK_VERSION:   returns ZIPKEY version information.
  137.  
  138.   In: AH = 070H
  139.  
  140.  Out: AX = The ZIPKEY program version number, as shown when
  141.          ZIPKEY is invoked or the ZIPKEY window is popped up.  AH
  142.          is the major version number (to the left of the decimal
  143.          point) and AL is the minor version number (to the right
  144.          of the decimal point).  For example, for V1.0 the return
  145.          AX value would be hex 100.
  146.  
  147.       CL = The number of states, (and territories, etc.) in the
  148.          current database.  Each state is assigned an internal
  149.          numeric code by ZIPKEY, that is used by many of the
  150.          functions of ZIPKEY's programmatic interface.  These
  151.          codes range from 0 to CL-1.
  152.  
  153.       DX = The date of the current ZIPKEY.OVL database.  DL is
  154.          the month, ranging from 1 for January to 12 for
  155.          December.  DH is the year minus 1900; e.g., decimal 89
  156.          for 1989.
  157.                                                               P-4
  158.  
  159. ZK_ABBR_ST:   converts a two-letter abbreviation into a state
  160.               code.
  161.  
  162.  In:  AH = 071H
  163.  
  164.       BX = The 2-letter ASCII abbreviation for the state, in
  165.          either upper- or lower-case.  BL is the first letter and
  166.          BH is the second letter.
  167.  
  168. Out:  AL = The ZIPKEY state code, suitable for input to other
  169.          ZIPKEY functions in this chapter.
  170.  
  171.          AL = 0FFH with the Carry flag set if not found.
  172.  
  173.  
  174. ZK_ST_ABBR:   converts a state code into a two-letter
  175.               abbreviation.
  176.  
  177.  In:  AH = 072H
  178.  
  179.       BL = The ZIPKEY state code, ranging from 0 through CL-1,
  180.          where CL is returned by ZK_VERSION.
  181.  
  182. Out:  AX = The 2-letter ASCII abbreviation, upper case.  AL is
  183.       the first letter and AH is the second letter.
  184.  
  185.       The Carry flag is set if the input state code BL was
  186.       invalid.
  187.  
  188.  
  189. ZK_ST_NAME:   converts a state code into a full state name.
  190.  
  191.  In:  AH = 073H
  192.  
  193.       BL = The ZIPKEY state code, as returned by ZK_ABBR_ST.
  194.  
  195.       ES:DI points to the buffer to contain the returned state
  196.       name.
  197.  
  198. Out:  The full state name is output to ES:DI-pointed memory. DI
  199.       is advanced beyond the output.
  200.  
  201.     The Carry flag is set if the input state code BL was invalid.
  202.                                                               P-5
  203.  
  204. ZK_ZIP_DIGITS:  converts zipcode DXCH into a ASCII digits string.
  205.  
  206.  In:  AH = 074H
  207.  
  208.       DX = The zip region, ranging from 0 to 999.
  209.  
  210.       CH = The last 2 digits of the zipcode, from 0 to 99.  Or,
  211.            if you want only 3 digits output, set CH to 255.
  212.  
  213. Out:  The 5 ASCII decimal digits of the zipcode are output to
  214.       ES:DI-pointed memory.  DI advanced beyond the output.
  215.  
  216.       The Carry flag is set if DX was greater than 999.
  217.  
  218.       NOTE this is not really a database function-- it is just
  219.       an unpacking function provided for convenience.
  220.  
  221.  
  222. ZK_ZIP_ST:   looks up the state code for zipcode DXCH.
  223.  
  224.  In:  AH = 075H
  225.  
  226.       DX = The zip region, ranging from 0 to 999.
  227.  
  228.       CH = The last 2 digits of the zipcode, from 0 to 99.
  229.  
  230. Out:  AL = the ZIPKEY state code.
  231.  
  232.       BX = the area code.
  233.  
  234.       The Carry flag is set, and AL=0FFH, if the zipcode
  235.       region (the first three digits) is invalid.
  236.  
  237.       Note: for speed, this routine does not check for validity
  238.       of the individual zipcode: it looks at only the zip
  239.       region and the state-exceptions list.  If you wish to
  240.       check the validity of a zipcode, use ZK_ZIP_CITY instead.
  241.                                                               P-6
  242.  
  243. ZK_ZIP_CITY: looks up the state and city for zipcode DXCH.
  244.  
  245.  In:  AH = 076H
  246.  
  247.       DX = The zip region, ranging from 0 to 999.
  248.  
  249.       CH = The last 2 digits of the zipcode, from 0 to 99.
  250.  
  251.       ES:DI points to the buffer to contain the returned city
  252.       name.
  253.  
  254. Out:  The ZIPKEY state code is returned in the AL register,
  255.       and the area code in the BX register.  The
  256.       city name is output to ES:DI-pointed memory.  DI is
  257.       advanced beyond the output.  To ensure that the name does
  258.       not exceed a maximum width, you can set the width using the
  259.       ZK_RESTORE function.  The Carry flag is set if the zipcode
  260.       was not found, with AL/DI set to the suggested state/city
  261.       if there is one.  AL is set to 0FFH if there is no
  262.       suggested city.
  263.  
  264.       NOTE that a previous call to ZK_ZIP_ST can and should be
  265.       made if you wish to suppress output for the not-found-but-
  266.       suggested case.
  267.  
  268.  
  269. ZK_ZIP_KEYS: plays the back exit key BX for the entry with
  270.              zipcode DXCH.
  271.  
  272.  In:  AH = 077H
  273.  
  274.       BX = The 16-bit BIOS keycode for a defined ZIPKEY alternate
  275.          exit key.  This is the code returned in the AX register
  276.          after you call the keyboard service routine (MOV AH,0
  277.          followed by INT 016H).  For example, the code for the F1
  278.          function key on a 100% IBM-compatible is 03B00H; add
  279.          0100H for subsequent function keys.
  280.  
  281.       DX = The zip region, ranging from 0 to 999.
  282.  
  283.       CH = The last 2 digits of the zipcode, from 0 to 99.
  284.  
  285. Out:  If there is a failure with no suggested city, ZIPKEY
  286.       returns Carry to the caller.  Otherwise, it returns
  287.       NoCarry, and the zipcode specification defined by the BX
  288.       exit-key is inserted into the BIOS keystrokes buffer, as if
  289.       a user had popped up the ZIPKEY window, typed in the
  290.       zipcode, and exited with the BX exit key.
  291.                                                               P-7
  292.  
  293. ZK_STCITY_ZIP:  looks up the zipcodes for a given state and city.
  294.  
  295.  In:  AH = 078H
  296.  
  297.       BL = The ZIPKEY state code for the city to be looked up.
  298.  
  299.       DS:SI points to the city-name specification.  The
  300.           specification is a string of ASCII characters,
  301.           terminated by a carriage-return (0DH) if the complete
  302.           name has been given, terminated by a null (00H) if
  303.           ZIPKEY should match any city whose name begins with the
  304.           specification, whether or not that is the complete city
  305.           name.  Letters in the string can be in either upper- or
  306.           lower-case.  ZIPKEY will also unabbreviate the string,
  307.           as described in Chapter 2.
  308.  
  309. Out:  ZIPKEY accumulates a list of all cities that match the
  310.       specification given.  The list is sorted first
  311.       alphabetically by city name, then numerically by zipcode.
  312.       Each entry on the list is a range of zipcodes for a city
  313.       that matches the specification.  If the first and last
  314.       zipcodes in the range are the same, the range consists of
  315.       just the one zipcode.  If they are different, then they
  316.       both represent valid codes for a matching city.  Any
  317.       zipcodes between the first and last may be either valid
  318.       zipcodes for the same city, or undefined zipcodes.
  319.  
  320.       The capacity of ZIPKEY's matching-entries buffer is 50. If
  321.       there are more than 50 entries for the specification,
  322.       ZIPKEY will return a count of 51 entries.  You may make
  323.       calls to ZK_CASE_ZIP to determine the entries returned, but
  324.       be aware that unless the complete count happened to be 51,
  325.       the list is incomplete.  The only way to obtain the
  326.       complete list of entries is to extend the city-name
  327.       specification by adding one or more letters in all possible
  328.       combinations.
  329.  
  330.       The zipcode range for the first entry is returned with this
  331.       call.  To obtain the remaining entries, you make repeated
  332.       calls to ZK_CASE_ZIP.  To obtain a readable display for
  333.       each entry, you call ZK_ZIP_CITY, ZK_ZIP_ST, and
  334.       ZK_ZIP_DIGITS.
  335.  
  336. The return register values are:
  337.  
  338.       BH = The number of matching entries (Carry set if BH=0). If
  339.          ZIPKEY's entries-buffer overflowed, BH is set to 51 (see
  340.          the above discussion about capacity).
  341.  
  342.       DX = The zip region (0 to 999) of the first entry.
  343.  
  344.       CL = The value of the bottom two digits for the first
  345.          zipcode in the range.
  346.  
  347.       CH = The value of the bottom two digits for the last
  348.          zipcode in the range.
  349.                                                               P-8
  350.  
  351. ZK_CITY_ZIP:   looks up zipcodes for a given city.
  352.  
  353.  In:  AH = 079H
  354.  
  355.       BL = The ZIPKEY state code of the first state to be
  356.          searched.
  357.  
  358.       DS:SI points to the city-name specification, just as in
  359.          ZK_STCITY_ZIP.
  360.  
  361. Out:  ZIPKEY accumulates a list of zipcode ranges, just as in
  362.       ZK_STCITY_ZIP.  With this function, however, if no matching
  363.       entries are found for state BL, then BL is incremented to
  364.       search in the next state.  Searching continues until either
  365.       a match is found or the last state code is reached.  If
  366.       there is no matching entry for the last state, ZIPKEY
  367.       returns AL=0FFH with the Carry flag set.  This differs from
  368.       the city-only search that is initiated interactively from
  369.       ZIPKEY's popup window-- the interactive search cycles
  370.       around to the first state and continues looking from there.
  371.  
  372.       To get a complete list of matching cities for all states,
  373.       you call this function first with BL=0, then repeat the
  374.       call with BL set to the previous returned AL+1, until you
  375.       get a failed find.
  376.  
  377.  
  378. The return register values are:
  379.  
  380.       AL = The ZIPKEY state code of the first matching state. AL
  381.          is set to 0FFH with Carry set if no state was found.
  382.  
  383.       BH = The number of matching entries (Carry set if BH=0). If
  384.          ZIPKEY's entries-buffer overflowed, BH is set to 51.
  385.  
  386.       DX = The zip region (0 to 999) of the first entry.
  387.  
  388.       CL = The value of the bottom two digits for the first
  389.          zipcode in the range.
  390.  
  391.       CH = The value of the bottom two digits for the last zipcode
  392.          in the range.
  393.                                                               P-9
  394.  
  395. ZK_CASE_ZIP:  fetches an entry from a previous ZK_(ST)CITY_ZIP
  396.               call.
  397.  
  398.  In:  AH = 07AH
  399.  
  400.       BL = a case number, from 0 to BH-1, where BH is the number
  401.          returned by the last call to ZK_STCITY_ZIP or
  402.          ZK_CITY_ZIP.
  403.  
  404. Out:  AL = The ZIPKEY state code for this entry.  Note that this
  405.          is the same value for all entries returned by a given
  406.          call to ZK_STCITY_ZIP or ZK_CITY_ZIP.
  407.  
  408.       DX = The zip region (0 to 999).
  409.  
  410.       CL = The bottom 2 digits (0 to 99) of the first zipcode in
  411.          the range.
  412.  
  413.       CH = the bottom 2 digits (0 to 99) of the last zipcode in
  414.          the range. CH = CL if there is only one zipcode.
  415.  
  416.  
  417. ZK_SAVE: fetches values necessary to save ZIPKEY's context.
  418.  
  419.  In:  AH = 07BH
  420.  
  421. Out:  BL = maximum number of characters for a ZK_ZIP_CITY city name.
  422.  
  423.       BH = the ZIPKEY state code for the last city-name search.
  424.  
  425.       BH = 0FF if there is no previous ZK_STCITY_ZIP or
  426.          ZK_CITY_ZIP call.
  427.  
  428.       CXDX = internal codes identifying the last city search
  429.  
  430.       This function is provided just in case somebody wishes to
  431.       incorporate ZIPKEY into a multitasking system, in which
  432.       more than one task might be using ZIPKEY.  The task-
  433.       switching code must call ZK_SAVE, record BX,CX, and DX as
  434.       part of the task state, and feed those values to ZK_RESTORE
  435.       before restarting the task.
  436.  
  437.       ZK_SAVE can also be used to read the current setting for
  438.       the maximum city width, returned in the BL register.
  439.                                                              P-10
  440.  
  441. ZK_RESTORE: restores ZIPKEY's context from a previous ZK_SAVE call.
  442.  
  443.  In:  AH = 07CH
  444.  
  445.       BL = the maximum number of characters for a city name.
  446.  
  447.       BH = the ZIPKEY state code returned by a previous ZK_SAVE
  448.          call.
  449.  
  450.       BH = 0FF if you are just setting the city width.
  451.  
  452.       CXDX = internal codes returned by a previous ZK_SAVE call.
  453.  
  454. Out:  Carry if BH,CX,DX are not codes which could have been
  455.       returned by a previous ZK_SAVE call
  456.  
  457.       This function will be used most often to set the maximum
  458.       city width.  It is also used in multitasking systems, as
  459.       described under the previous function ZK_SAVE.
  460.  
  461.  
  462. ZK_POPUP:   pops up a ZIPKEY window from a program.
  463.  
  464.  In:  AH = 07DH
  465.  
  466.       BL = an index number if you wish to simulate the pressing of
  467.          a hotkey.
  468.  
  469.       BL = 0FF for immediate popup with nothing played back after
  470.          a confirming Enter key.
  471.  
  472. Out:  ZIPKEY takes action as if the hotkey indexed by BL has been
  473.       pressed.  This typically includes popping up a window,
  474.       waiting for the user to type a zipcode specification, and
  475.       playing back an indicated sequence through the BIOS
  476.       keystrokes buffer.  The values of BL are defined by the
  477.       listing of hotkeys available from the configuration editing
  478.       menu: BL=0 for the first hotkey, BL=1 for the second, etc.
  479.       If BL is not a valid index ZIPKEY pops up a window, then
  480.       plays back nothing if a confirming Enter is given (ZIPKEY
  481.       will play back alternate exit keys, however).  ZIPKEY does
  482.       not return from this interrupt call until the window is
  483.       popped away-- then it returns NoCarry.
  484.                                                              P-11
  485.  
  486. ZK_REGION_CITY:   outputs the name of the primary city for a
  487.                   zipcode region.
  488.  
  489.  In:  AH = 07EH
  490.  
  491.       DX = The zip region, ranging from 0 to 999.
  492.  
  493.       ES:DI points to the buffer to contain the returned city
  494.          name.
  495.  
  496. Out:  AL = The ZIPKEY state code for the region if the region
  497.       exists.  BX is set to the area code.
  498.       The name of primary city for this region is output
  499.       to ES:DI-pointed memory.  DI is advanced beyond the output.
  500.       AL = 0FF with the Carry flag set if the region does not
  501.       exist.
  502.  
  503.  
  504. ZK_SWITCH:   enables/disables hotkeys and/or DOS recursion checking.
  505.  
  506.  In:  AH = 07FH
  507.  
  508.       BL = a control code:
  509.             0 for turn off hotkeys
  510.             1 for turn on hotkeys
  511.             2 for no change, just return hotkey status
  512.             3 for toggle hotkey status
  513.             6 for disabling DOS recursion checking
  514.  
  515. Out:  The activation of hotkeys is disabled/enabled/reported.
  516.       When a hotkey is disabled ZIPKEY ignores it, and it reverts
  517.       to its non-ZIPKEY functionality.  AL is returned set to the
  518.       hotkeys status: 0 for off (disabled), 1 for on (enabled).
  519.  
  520.       If BL=6, ZIPKEY's program interface
  521.       (INT 179) no longer checks
  522.       to see if DOS is busy and cannot be called.  It is the calling
  523.       program's responsibility to insure that DOS can be called.
  524.  
  525. ZK_AREA_ST:   Delivers the state associated with area code BX.
  526.  
  527.  In:  AH = 080H
  528.       BX = area code (decimal integer)
  529.  
  530. Out:  AL = the ZIPKEY state code for the area code, if the area code
  531.       exists.  DX is set to the first zip region associated with that
  532.       state, and CX to the number of zip regions until the last
  533.       region associated with the state.  You must make CX subsequent
  534.       calls to ZK_REGION_CITY to find which regions are actually within
  535.       the state, and/or contain the area code wanted.
  536.  
  537.       If the area code is Canadian, we return a special state code
  538.       that will be honored by ZK_ST_ABBR and ZK_ST_NAME, but the
  539.       region DX is set to 1000.  If the area code does not exist,
  540.       we return Carry, AL=0FFH and DX=1001.
  541.                                                              P-12
  542.  
  543. Sample Program Code
  544.  
  545. Following are fragments of assembly-language code that call
  546. ZIPKEY's programmatic interface.  I've tried to make them
  547. compatible with all the major assemblers, although they are
  548. tested only against my A86 assembler. If you do use my A86
  549. assembler, and you reuse the local labels L3, L4, L6, L8, and L10
  550. elsewhere in your program, you should insert ">" into their
  551. forward references in the following code: JC >L3; JC >L4; JMP
  552. >L6, JNE >L8, JE >L10.
  553.  
  554. RO_NAME:
  555.   DB 'RO',0
  556. NOME_NAME:
  557.   DB 'nome',0DH
  558.  
  559.  
  560. ; output a list of states to memory at 08000H
  561.  
  562. L0:
  563.   MOV AH,070H       ; ZIPKEY function number ZK_VERSION
  564.   INT 179           ; fetch the version information
  565.   MOV CH,0          ; extend states count CL to CX
  566.   MOV BL,0          ; load the first state code
  567.   MOV DI,08000H     ; load the output pointer
  568. L1:                 ; loop here to output each state name
  569.   MOV AH,072H       ; ZIPKEY function number ZK_ST_ABBR
  570.   INT 179           ; fetch the state abbreviation
  571.   STOSW             ; output the abbreviation
  572.   MOV AL,' '        ; load blank
  573.   STOSB             ; output an intervening blank
  574.   MOV AH,073H       ; ZIPKEY function number ZK_ST_NAME
  575.   INT 179           ; output the full state name
  576.   MOV AX,0A0DH      ; load CRLF
  577.   STOSW             ; output CRLF to end this line
  578.   INC BL            ; increment BL to the next state code
  579.   LOOP L1           ; loop to output the next state
  580.                                                              P-13
  581.  
  582. ; output to memory the list of valid zipcodes for region 474
  583.  
  584.   MOV DX,474        ; load the region number
  585.   MOV DI,08000H     ; load the output pointer
  586.   MOV CH,0          ; the first zipcode has bottom digits 00
  587. L2:                 ; loop here to output each entry
  588.   MOV AH,075H       ; ZIPKEY function number ZK_ZIP_ST
  589.   INT 179           ; check the validity of this zipcode
  590.   JC L3             ; skip if this is not a valid zipcode
  591.   MOV BL,AL         ; zipcode valid: copy state code to BL
  592.   MOV AH,074H       ; ZIPKEY function number ZK_ZIP_DIGITS
  593.   INT 179           ; output the zipcode digits
  594.   MOV AL,' '        ; load blank
  595.   STOSB             ; output an intervening blank
  596.   CALL CITY_ST_CRLF ; output the city, state, and CRLF
  597. L3:
  598.   INC CH            ; increment the bottom 2 digits counter
  599.   CMP CH,100        ; have we completed the region?
  600.   JB L2             ; loop if not, to output the next line
  601.  
  602.  
  603. ; output a list of Illinois cities starting with RO
  604.  
  605.   MOV DI,08000H     ; load the output pointer
  606.   MOV BX,'LI'       ; characters IL are reversed on the 8086
  607.   MOV AH,071H       ; ZIPKEY function number ZK_ABBR_ST
  608.   INT 179           ; fetch the state code for this abbreviation
  609.   MOV BL,AL         ; copy the state code to BL
  610.   PUSH CS           ; push our code segment
  611.   POP DS                 ; set DS to our code segment
  612.   MOV SI,OFFSET RO_NAME  ; point to "RO" city specification
  613.   MOV AH,078H            ; ZIPKEY function number ZK_STCITY_ZIP
  614.   INT 179           ; get the list of entries for this city
  615.   JC L4             ; skip if the list was empty
  616.   CALL OUT_ENTRIES
  617. L4:
  618.  
  619.  
  620. ; output a list of Nomes in the United States
  621.  
  622.   MOV DI,08000H            ; load the output pointer
  623.   PUSH CS                  ; push our code segment
  624.   POP DS                   ; set DS to our code segment
  625.   MOV SI,OFFSET NOME_NAME  ; point to "Nome" specification
  626.   MOV BL,0                 ; first state code is zero
  627.   JMP L6                   ; jump into loop
  628.  
  629. L5:                        ; loop here for each matching state
  630.   PUSH AX                  ; save the state code
  631.   CALL OUT_ENTRIES         ; output the entries for this state
  632.   POP BX                   ; restore the state code to BL
  633.   INC BX                   ; increment to the next state
  634. L6:
  635.   MOV AH,079H              ; ZIPKEY function number ZK_CITY_ZIP
  636.   INT 179                  ; find a state with the desired city
  637.   JNC L5                   ; loop if found, to make display
  638.                                                              P-14
  639.  
  640. ; set the maximum city width to 17
  641.  
  642.   MOV BL,17         ; load the desired city width
  643.   MOV BH,0FFH       ; code signals that we load width only
  644.   MOV AH,07CH       ; ZIPKEY function number ZK_RESTORE
  645.   INT 179           ; set the city width
  646.  
  647.  
  648. ; save and restore ZIPKEY context
  649.  
  650.   MOV AH,07BH       ; ZIPKEY function number ZK_SAVE
  651.   INT 179           ; fetch the ZIPKEY context
  652.   PUSH BX           ; push the context onto our stack
  653.   PUSH CX
  654.   PUSH DX
  655. ; ....
  656.   POP DX            ; pop the saved context
  657.   POP CX
  658.   POP BX
  659.   MOV AH,07CH       ; ZIPKEY function number ZK_RESTORE
  660.   INT 179           ; restore the ZIPKEY context
  661.  
  662.  
  663. ; popup a window as if the first hotkey were pressed
  664.  
  665.   MOV AH,07DH       ; ZIPKEY function number ZK_POPUP
  666.   MOV BL,0          ; index for the first hotkey is zero
  667.   INT 179           ; popup the ZIPKEY window
  668.  
  669.  
  670. ; insert keystrokes for zipcode 47401, as if alternate
  671. ;   exit key F1 had been pressed
  672.  
  673.   MOV DX,474        ; load the region number 474
  674.   MOV CH,01         ; load the last two digits 01
  675.   MOV BX,03B00      ; load the BIOS code for the F1 key
  676.   MOV AH,077H       ; ZIPKEY function number ZK_ZIP_KEYS
  677.   INT 179           ; insert keystrokes for 47401 entry
  678.  
  679.  
  680. ; toggle the activation of ZIPKEY's hotkeys
  681.  
  682.   MOV BL,3          ; control code for "toggle"
  683.   MOV AH,07FH       ; ZIPKEY function number ZK_SWITCH
  684.   INT 179           ; toggle the activation of hotkeys
  685.                                                              P-15
  686.  
  687. ; output to DI a list of sample cities for area code 512
  688.  
  689.   MOV BP,512      ; load the area code number
  690.   MOV DI,08000H   ; load the output pointer
  691.   MOV DX,BP       ; set DX to the area code
  692.   CALL OUT_DX3    ; output the area code
  693.   MOV BX,BP       ; copy the area code to BX, for ZK_AREA_ST
  694.   MOV AH,080H     ; function code for ZK_AREA_ST
  695.   INT 179         ; set AL to the state code for area code BX
  696.   JC OUT_CRLF     ; exit if the area code did not exist
  697.   MOV BL,AL       ; we have a state code: copy it to BL
  698.   MOV AH,073H     ; function code for ZK_ST_NAME
  699.   INT 179         ; output the name of this area code's state
  700.   CALL OUT_CRLF   ; output a CRLF to complete the header line
  701.   CMP DX,1000     ; was it a Canadian area code?
  702.   JAE OUT_CRLF    ; skip if it was
  703. L7:               ; loop here to check each zip region
  704.   PUSH DI         ; save the output pointer
  705.   ADD DI,6        ; advance pointer to the city-name column
  706.   MOV AH,07EH     ; function code for ZK_REGION_CITY
  707.   INT 179         ; output the city name for this region
  708.   CMP BX,BP       ; does the city have the correct area code?
  709.   MOV AX,DI       ; save the end-of-line output pointer
  710.   POP DI          ; restore the start-of-line output pointer
  711.   JNE L8          ; cancel the line if it wasn't our area code
  712.   PUSH AX         ; we do have our area code: save end pointer
  713.   MOV AX,'  '     ; load two blanks
  714.   STOSW           ; output a two-blank indentation
  715.   CALL OUT_DX3    ; output the area code
  716.   POP DI          ; restore the end-of-line pointer
  717.   CALL OUT_CRLF   ; output the terminating CRLF
  718. L8:
  719.   INC DX          ; advance DX to the next zip region
  720.   LOOP L7         ; loop to check the next region
  721.                                                              P-16
  722.  
  723. CITY_ST_CRLF:     ; subroutine for outputting a city line
  724.   PUSH DX         ; preserve register across call
  725.   MOV AH,076H     ; ZIPKEY function number ZK_ZIP_CITY
  726.   INT 179         ; output the city name
  727.   MOV DX,BX       ; copy the area code to DX, for output
  728.   MOV BL,AL       ; copy the state code to BL
  729.   MOV AL,' '      ; load blank
  730.   STOSB           ; output an intervening blank
  731.   MOV AH,072H     ; ZIPKEY function number ZK_ST_ABBR
  732.   INT 179         ; fetch the state abbreviation
  733.   STOSW           ; output the state abbreviation
  734.   MOV AX,'( '     ; load a space and a left paren
  735.   STOSW           ; output a space and a left paren
  736.   CALL OUT_DX3    ; output the area code
  737.   DEC DI          ; retract the trailing blank
  738.   MOV AL,')'      ; load a right paren
  739.   STOSB           ; output a right paren
  740.   POP DX          ; restore clobbered register
  741. OUT_CRLF:         ; subroutine for outputting line terminator
  742.   MOV AX,0A0DH    ; load CRLF
  743.   STOSW           ; output CRLF
  744.   RET
  745.  
  746.  
  747. OUT_DX3:            ; subroutine for outputting 3-digit DX
  748.   PUSH CX           ; preserve register across call
  749.   MOV CH,0FFH       ; CH code suppresses the final two digits
  750.   MOV AH,074H       ; function code for ZK_ZIP_DIGITS
  751.   INT 179           ; output the 3-digit code
  752.   MOV AL,' '        ; load blank
  753.   STOSB             ; output a trailing blank
  754.   POP CX            ; restore clobbered register
  755.   RET
  756.                                                              P-17
  757.  
  758. OUT_ENTRIES:        ; subroutine for outputting a cities-range
  759.   MOV BL,0          ; load the first entry number
  760. L9:                 ; loop here to output each entry
  761.   PUSH BX           ; save the entry number during output
  762.   PUSH DI           ; save the starting output pointer
  763.   ADD DI,5          ; advance beyond the zipcode we will output
  764.   MOV AX,'  '       ; load blanks
  765.   STOSW             ; blank out the trailing range slot
  766.   STOSW             ; slot plus trailing blank are 4 characters
  767.   POP DI            ; restore the pointer to the line start
  768.   MOV AH,07AH       ; ZIPKEY function number ZK_CASE_ZIP
  769.   INT 179           ; look up this entry
  770.   MOV BL,AL         ; copy the state code to BL
  771.   CMP CL,CH         ; is there only one zipcode?
  772.   JE L10            ; skip if single zipcode: slot stays blank
  773.   PUSH DI           ; it is a range: save output pointer
  774.   ADD DI,3          ; advance the output pointer
  775.   MOV AH,074H       ; ZIPKEY function number ZK_ZIP_DIGITS
  776.   INT 179           ; output the end-value zipcode digits
  777.   POP DI            ; restore starting output pointer
  778.   ES MOV BYTE PTR [DI+5],'-' ; place the trailing hyphen
  779.   MOV CH,CL         ; copy the start-value to CH
  780. L10:
  781.   MOV AH,074H       ; ZIPKEY function number ZK_ZIP_DIGITS
  782.   INT 179           ; output the start-value zipcode digits
  783.   ADD DI,4          ; advance beyond the end-value slot
  784.   CALL CITY_ST_CRLF ; output the city, state, CRLF
  785.   POP BX            ; restore the entry number BL
  786.   INC BL            ; increment the entry number
  787.   CMP BL,BH         ; have we exhausted the entries?
  788.   JB L9             ; loop if not, to output the next entry
  789.   RET
  790.  
  791.